/**
 * @Version 1.0.0
 * @Author ZhenYuTsai
 * @Descripttion
 * @Date 2022-01-12 11:46:53
 * @LastEditors ZhenYuTsai
 */
import Vue from 'vue'
import TRTC from 'trtc-js-sdk'
import imClient from './im-client.js'
export default new Vue({
  data () {
    return {
      sdkAppId: null,
      userId: null,
      userSig: null,
      roomId: null,
      client: null,
      isJoined: false,
      localStream: null,
      remoteStreams: []
    }
  },
  methods: {
    // 初始化实时音视频
    init ({ sdkAppId, userId, userSig, roomId }) {
      return new Promise(resolve => {
        this.sdkAppId = sdkAppId
        this.userId = userId
        this.userSig = userSig
        this.roomId = roomId

        // 输出INFO以上日志等级
        TRTC.Logger.setLogLevel(TRTC.Logger.LogLevel.INFO)

        // 创建实时音视频客户端
        this.client = TRTC.createClient({
          mode: 'rtc',
          sdkAppId: this.sdkAppId,
          userId: this.userId,
          userSig: this.userSig
        })

        // 开启音量回调，并设置每 1000ms 触发一次事件
        this.client.enableAudioVolumeEvaluation(1000)

        // 启动监听事件
        this.handleEvents()

        resolve('success')
      })
    },
    // 加入房间
    async join () {
      return new Promise((resolve, reject) => {
        if (this.isJoined) {
          console.warn('duplicate RtcClient.join() observed')
          reject(new Error('duplicate RtcClient.join() observed'))
        }
        // 加入房间
        this.client.join({
          roomId: parseInt(this.roomId)
        }).then(() => {
          console.log('join room success')
          this.isJoined = true
          // 创建本地流
          this.localStream = TRTC.createStream({
            audio: true,
            video: true,
            userId: this.userId,
            mirror: true
          })
          // 初始化本地音视频流对象
          this.localStream.initialize().then(() => {
            console.log('initialize local stream success')
            this.localStream.on('player-state-changed', event => {
              console.log(`local stream ${event.type} player is ${event.state}`)
            })
            resolve('success')
          }).catch((error) => {
            console.error('failed to initialize local stream - ' + error)
            reject(error)
            switch (error.name) {
              case 'NotReadableError':
                alert(
                  '暂时无法访问摄像头/麦克风，请确保系统允许当前浏览器访问摄像头/麦克风，并且没有其他应用占用摄像头/麦克风'
                )
                return
              case 'NotAllowedError':
                if (error.message === 'Permission denied by system') {
                  alert('请确保系统允许当前浏览器访问摄像头/麦克风')
                } else {
                  console.log('User refused to share the screen')
                }
                return
              case 'NotFoundError':
                alert(
                  '浏览器获取不到摄像头/麦克风设备，请检查设备连接并且确保系统允许当前浏览器访问摄像头/麦克风'
                )
              // eslint-disable-next-line no-fallthrough
              default:
              // eslint-disable-next-line no-useless-return
                return
            }
          })
        }).catch((error) => {
          console.error('join room failed! ' + error)
          reject(error)
        })
      })
    },
    // 本地离开
    async leave () {
      if (!this.isJoined) {
        console.warn('leave() - please join() firstly')
        return
      }
      // ensure the local stream is unpublished before leaving.
      await this.unpublish()

      // 本地客户端离开
      await this.client.leave()

      this.localStream.stop()
      this.localStream.close()
      this.localStream = null
      this.isJoined = false
      // 停止获取音量
      this.stopGetAudioLevel()
    },
    // 事件监听
    handleEvents () {
      const that = this
      // 监听报错信息
      this.client.on('error', err => {
        console.error(err)
        alert(err)
      })
      // 监听踢出房间事件
      this.client.on('client-banned', err => {
        console.error('client has been banned for ' + err)
      })
      // 远端用户加入房间事件
      this.client.on('peer-join', evt => {
        const userId = evt.userId
        console.log('peer-join ' + userId)
      })
      // 远端用户离开房间事件
      this.client.on('peer-leave', evt => {
        const userId = evt.userId
        console.log('peer-leave ' + userId)
      })
      // 远端流新增事件
      this.client.on('stream-added', evt => {
        const remoteStream = evt.stream
        const id = remoteStream.getId()
        const userId = remoteStream.getUserId()
        console.log(`remote stream added: [${userId}] ID: ${id} type: ${remoteStream.getType()}`)
        // 订阅远端流
        this.client.subscribe(remoteStream)
      })
      // 远端流订阅成功事件
      this.client.on('stream-subscribed', evt => {
        const uid = evt.stream.getUserId()
        const remoteStream = evt.stream
        const id = remoteStream.getId()
        const audio = remoteStream.hasAudio()
        console.log(`remote stream subscribed: [${uid}] ID: ${id} type: ${remoteStream.getType()}`)
        remoteStream.on('player-state-changed', event => {
          console.log(`${event.type} player is ${event.state}`)
        })
        /* ------ 特别注意这里调用了imClient,查询远端流的用户信息------- */
        imClient.getUserProfile(uid).then((result) => {
          console.log(result, '查询用户信息')
          let nick = '暂无昵称'
          if (result.code === 0 && result.data.length > 0) {
            nick = result.data[0].nick || '暂无昵称'
          }
          // 添加远端用户信息和远端流到列表
          this.remoteStreams.push({ id, userId: uid, remoteStream, audio: audio ? 0 : 1, nick })
          // 播放远端流
          this.$nextTick(() => {
            remoteStream.play(id)
          })
          // 抛出混流回调方法
          this.$emit('MIX_VIDEO', { localStream: this.localStream, remoteStreams: this.remoteStreams })
        /* ------ 项目如果没有需要或者没有接入imClient,请删除以上查询信息内容 ------ */
        }).catch((err) => {
          console.log(err)
        })
      })
      // 远端流离开事件
      this.client.on('stream-removed', evt => {
        const remoteStream = evt.stream
        const id = remoteStream.getId()
        remoteStream.stop()
        this.remoteStreams = this.remoteStreams.filter(item => {
          return item.remoteStream.getId() !== id
        })
        console.log(`stream-removed ID: ${id}  type: ${remoteStream.getType()}`)
        // 抛出取消混流回调方法
        this.$emit('CANCEL_MIX_VIDEO', { localStream: this.localStream, remoteStreams: this.remoteStreams })
      })
      // 远端流更新事件，当远端用户添加、移除或更换音视频轨道后会收到该通知
      this.client.on('stream-updated', evt => {
        const remoteStream = evt.stream
        console.log('type: ' + remoteStream.getType() + ' stream-updated hasAudio: ' + remoteStream.hasAudio() + ' hasVideo: ' + remoteStream.hasVideo())
      })
      // 远端用户禁用音频通知
      this.client.on('mute-audio', evt => {
        console.log(evt.userId + ' mute audio')
        const index = that.remoteStreams.findIndex(item => {
          return item.userId === evt.userId
        })
        if (index > -1) {
          that.remoteStreams[index].audio = 1
        }
      })
      // 远端用户启用音频通知
      this.client.on('unmute-audio', evt => {
        console.log(evt.userId + ' unmute audio')
        const index = that.remoteStreams.findIndex(item => {
          console.log(item, evt.userId)
          return item.userId === evt.userId
        })
        if (index > -1) {
          that.remoteStreams[index].audio = 0
        }
      })
      // 远端用户音量变化
      this.client.on('audio-volume', evt => {
        evt.result.forEach(({ userId, audioVolume, stream }) => {
          // console.log(`user: ${userId} is speaking, audioVolume: ${audioVolume}`)
          if (audioVolume > 10) {
            const index = that.remoteStreams.findIndex(item => item.userId === userId)
            if (index > -1) {
              that.remoteStreams[index].audio = 2
            }
          }
        })
      })
      // 远端用户禁用视频通知
      this.client.on('mute-video', evt => {
        console.log(evt.userId + ' mute video')
      })
      // 远端用户启用视频通知
      this.client.on('unmute-video', evt => {
        console.log(evt.userId + ' unmute video')
      })
    },
    // 播放本地流
    playLocalStream (id = 'main-video') {
      this.localStream.play(id)
    },
    // 推送本地流
    async publish () {
      if (!this.isJoined) {
        console.warn('publish() - please join() firstly')
        return
      }
      if (this.isPublished) {
        console.warn('duplicate RtcClient.publish() observed')
        return
      }
      try {
        await this.client.publish(this.localStream)
      } catch (error) {
        console.error('failed to publish local stream ' + error)
        this.isPublished = false
      }
      this.isPublished = true
    },
    // 取消推送本地流
    async unpublish () {
      if (!this.isJoined) {
        console.warn('unpublish() - please join() firstly')
        return
      }
      if (!this.isPublished) {
        console.warn('RtcClient.unpublish() called but not published yet')
        return
      }

      await this.client.unpublish(this.localStream)
      this.isPublished = false
    },
    // 禁用本地音频
    muteLocalAudio () {
      this.localStream.muteAudio()
    },
    // 启用本地音频
    unmuteLocalAudio () {
      this.localStream.unmuteAudio()
    },
    // 禁用本地视频
    muteLocalVideo () {
      this.localStream.muteVideo()
    },
    // 启用本地视频
    unmuteLocalVideo () {
      this.localStream.unmuteVideo()
    },
    // 显示流状态
    showStreamState (stream) {
      console.log('has audio: ' + stream.hasAudio() + ' has video: ' + stream.hasVideo())
    },
    // 停止获取流音量
    stopGetAudioLevel () {
      this.client.enableAudioVolumeEvaluation(-1)
    },
    // 截取当前视频帧
    getVideoFrame (stream) {
      const frame = stream.getVideoFrame()
      return frame
    }
  }
})
